package com.gpc.hexapods.layer;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.SeekBar;


import com.gpc.hexapods.R;

import java.lang.ref.WeakReference;

public class ControlLayout extends RelativeLayout {

    private static final String TAG = "CtrlSeekBarLayout";

    private static final int DEFAULT_PROGRESS = 50;
    private static final float SPEED_MAX = 1.0f;

    private static final int MSG_UPDATE = 1;
    private static final int MSG_STOP = 2;
    private static final int DELAY_TIME = 500;

    private RelativeLayout mTurnLayout;
    private SeekBar mTurnSeekBar;
    private SeekBar mGoSeekBar;

    private CtrlHandler mCtrlHandler;
    private HandlerThread mHandlerThread;
    private OnCtrlListener mCtrlListener;
    private Vibrator mVibrator;

    private float mAngularSpeed;
    private float mLinearSpeed;

    public ControlLayout(Context context) {
        this(context, null);
    }

    public ControlLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ControlLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View view = LayoutInflater.from(context).inflate(R.layout.control_layout, this);
        initView(view);
        initListener();
        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    }

    public void setCtrlListener(OnCtrlListener ctrlListener) {
        mCtrlListener = ctrlListener;
    }

    public void setScreen(int screenType) {
        /*RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mTurnLayout.getLayoutParams();
        if (screenType == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            layoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        } else {
            layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
            layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        }*/
    }

    private void initView(View view) {
        mTurnLayout = view.findViewById(R.id.ctrl_turn_layout);
        mTurnSeekBar = view.findViewById(R.id.ctrl_turn_seek_bar);
        mGoSeekBar = view.findViewById(R.id.ctrl_go_seek_bar);
    }

    private void initListener() {
        mTurnSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mAngularSpeed = (progress - DEFAULT_PROGRESS) * SPEED_MAX / DEFAULT_PROGRESS ;
                sendUpdateMsg();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                mVibrator.vibrate(50);
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Log.i(TAG, "turn onStop");
                mTurnSeekBar.setProgress(DEFAULT_PROGRESS);
            }
        });

        mGoSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mLinearSpeed = (progress - DEFAULT_PROGRESS) * SPEED_MAX / DEFAULT_PROGRESS;
                sendUpdateMsg();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                mVibrator.vibrate(50);
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Log.i(TAG, "go onStop");
                mGoSeekBar.setProgress(DEFAULT_PROGRESS);
            }
        });
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.i(TAG, "onAttachedToWindow");
        if (mHandlerThread == null) {
            mHandlerThread = new HandlerThread(CtrlHandler.class.getName());
            mHandlerThread.start();
        }
        mCtrlHandler = new CtrlHandler(mHandlerThread.getLooper(), new WeakReference<>(this));
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Log.i(TAG, "onDetachedFromWindow");
        if (mHandlerThread != null) {
            mHandlerThread.quit();
            mHandlerThread = null;
        }
        if (mCtrlHandler != null) {
            mCtrlHandler.removeCallbacksAndMessages(null);
            mCtrlHandler = null;
        }
        mCtrlListener = null;
    }

    private void sendUpdateMsg() {
        if (mCtrlHandler == null) {
            return;
        }
        if (mAngularSpeed != 0 || mLinearSpeed != 0) {
            mCtrlHandler.removeCallbacksAndMessages(null);
            mCtrlHandler.sendEmptyMessage(MSG_UPDATE);
        } else {
            mCtrlHandler.removeCallbacksAndMessages(null);
            mCtrlHandler.sendEmptyMessage(MSG_STOP);
        }
    }

    private static class CtrlHandler extends Handler {

        private WeakReference<ControlLayout> mLayout;

        CtrlHandler(Looper looper, WeakReference<ControlLayout> layout) {
            super(looper);
            mLayout = layout;
        }

        @Override
        public void handleMessage(Message msg) {
            ControlLayout layout = mLayout.get();
            if (layout == null || !layout.isAttachedToWindow()) {
                Log.d(TAG, "layout is null !");
                return;
            }
            switch (msg.what) {
                case MSG_UPDATE:
                    if (layout.mCtrlListener != null) {
                        layout.mCtrlListener.onCtrlListener(layout.mLinearSpeed, layout.mAngularSpeed);
                    }
                    removeCallbacksAndMessages(null);
                    if (layout.mAngularSpeed != 0 || layout.mLinearSpeed != 0) {
                        sendEmptyMessageDelayed(MSG_UPDATE, DELAY_TIME);
                    } else {
                        sendEmptyMessage(MSG_STOP);
                    }
                    break;

                case MSG_STOP:
                    if (layout.mCtrlListener != null) {
                        layout.mCtrlListener.onCtrlListener(0, 0);
                    }
                    break;
            }
        }
    }

    public interface OnCtrlListener {
        void onCtrlListener(float linearSpeed, float angularSpeed);
    }
}
